package com.fire.web.modules.all.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.fire.web.modules.all.constant.ErrorCodeConstants;
import com.fire.web.modules.all.entity.AjaxResult;
import com.fire.web.modules.all.entity.FireProprietorModel;
import com.fire.web.modules.all.entity.SiteModel;
import com.fire.web.modules.all.service.IFireProprietorService;
import com.fire.web.modules.all.service.ISiteService;
import com.fire.web.modules.all.utils.TokenUtil;
import com.fire.web.modules.all.validation.AssetEventDTO;
import com.fire.web.modules.sso.service.IOAuthService;
import com.fire.web.security.shiro.realm.UserRealm;
import com.smartthing.rest.model.device.event.DeviceAlert;
import com.smartthing.rest.model.device.event.DeviceLocation;
import com.smartthing.rest.model.device.event.DeviceMeasurements;
import com.smartthing.rest.model.search.DateRangeSearchCriteria;
import com.smartthing.rest.model.search.DeviceAlertSearchResults;
import com.smartthing.rest.model.search.DeviceLocationSearchResults;
import com.smartthing.rest.model.search.DeviceMeasurementsSearchResults;
import com.smartthing.spi.ISmartThingClient;
import com.smartthing.spi.SmartThingException;
import com.smartthing.spi.device.DeviceAssignmentType;
import com.smartthing.spi.device.event.AlertLevel;
import com.smartthing.spi.device.event.AlertSource;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/asset")
public class EventController {
	private final static Logger logger = Logger.getLogger(EventController.class);
	private final static String YES = "YES";

	@Autowired
	private ISiteService siteService;

	@Autowired
	private SolrClient client;

	@Autowired
	private IOAuthService oAuthService;

	@Autowired
	private IFireProprietorService fireProprietorService;

	@Autowired
	private ISmartThingClient smartThingClient;
	@Value("${spring.data.solr.core}")
	private String core;

	/**
	 * 查询消防资产事件链表
	 *
	 * @return
	 * @author zengzhengfu
	 */
	@PostMapping(value = "/assetevent")
	@ResponseBody
	public AjaxResult assetevent(@Validated AssetEventDTO assetEventDTO, BindingResult bindingResult,
								 HttpServletRequest request, HttpServletResponse response) {
		if (bindingResult.hasErrors()) {
			for (FieldError fieldError : bindingResult.getFieldErrors()) {
				String message = fieldError.getDefaultMessage();
				logger.error(message);
				return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "参数有误," + message, "参数有误," + message);
			}
		}
		if (YES.equals(assetEventDTO.getIsalert())) {
			//历史告警使用接口查询
			if (YES.equals(assetEventDTO.getHistory())) {
				//只有站点id
				return getSiteAlerts(assetEventDTO);
			}
			//非历史告警使用solr查询
			return getSiteAlertsBySolr(assetEventDTO);
		}
		String assetid = assetEventDTO.getAssetid();

		String token = TokenUtil.getToken(request, response);
		UserRealm.Principal principalByAccessToken = oAuthService.getPrincipalByAccessToken(token);
		String id = principalByAccessToken.getId();

		EntityWrapper<FireProprietorModel> proprietorWrapper = new EntityWrapper<>();
		proprietorWrapper.eq("adminid",id);
		FireProprietorModel proprietor = fireProprietorService.selectOne(proprietorWrapper);

		EntityWrapper<SiteModel> siteWrapper = new EntityWrapper<>();
		siteWrapper.eq("proprietor",proprietor.getProprietor());
		SiteModel site = siteService.selectOne(siteWrapper);

		String siteid = assetEventDTO.getSiteid();
		if (StringUtils.isBlank(siteid)){
			siteid = site.getSiteid();
		}
		//有资产id，使用solr查询;无站点id，也无资产id，则查询所有事件
		if (StringUtils.isNotBlank(assetEventDTO.getAssetid()) || (StringUtils.isBlank(siteid) && StringUtils.isBlank(assetid))) {
			if (YES.equals(assetEventDTO.getIsmeasurement())) {
				//返回站点测量
				return getSiteMeasurementsBySolr(assetEventDTO);
			} else {
				//返回站点位置
				return getSiteLocationsBySolr(assetEventDTO);
			}
		} else {
			//无资产id，查询站点下的所有位置或测量，使用SmartThing提供的借口查询
			if (YES.equals(assetEventDTO.getIsmeasurement())) {
				//返回站点测量
				return getSiteMeasurements(assetEventDTO);
			} else {
				//返回站点位置
				return getSiteLocations(assetEventDTO);
			}
		}
	}


	private AjaxResult getSiteAlertsBySolr(AssetEventDTO assetEventDTO) {
		try {
			SolrQuery params = new SolrQuery();
			//查询条件
			params.set("q", "eventType:Alert");

			params = getParams(params, assetEventDTO);

			//yml文件未配置具体的collection，所以此处需要配置
			QueryResponse queryResponse = client.query(core, params);

			SolrDocumentList results = queryResponse.getResults();

			DeviceAlertSearchResults searchResults = new DeviceAlertSearchResults();
			searchResults.setNumResults(results.getNumFound());
			List<DeviceAlert> responseResult = new ArrayList<>();
			for (SolrDocument document : results) {
				DeviceAlert alert = new DeviceAlert();

				alert.setId((String) document.get("eventId"));
				alert.setDeviceAssignmentToken((String) document.get("assignmentToken"));

				String assignmentType = (String) document.get("assignmentType");
				DeviceAssignmentType assignmentTypeEnum = (DeviceAssignmentType) getEnum(assignmentType, DeviceAssignmentType.values());
				alert.setAssignmentType(assignmentTypeEnum);

				String assetId = (String) document.get("assetId");
				alert.setAssetId(assetId);
				String siteToken = (String) document.get("siteToken");
				alert.setSiteToken(siteToken);

				Date eventDate = (Date) document.get("eventDate");
				alert.setEventDate(eventDate);
				Date receivedDate = (Date) document.get("receivedDate");
				alert.setReceivedDate(receivedDate);

				alert.setType(document.get("alertType").toString());
				alert.setMessage((String) document.get("alertMessage"));
				String level = (String) document.get("alertLevel");
				AlertLevel alertEnum = (AlertLevel) getEnum(level, AlertLevel.values());
				alert.setLevel(alertEnum);
				String alertSource = (String) document.get("alertSource");
				AlertSource sourceEnum = (AlertSource) getEnum(alertSource, AlertSource.values());
				alert.setSource(sourceEnum);
				Map meta = getmetadata(document, "meta");
				alert.setMetadata(meta);
				responseResult.add(alert);
			}

			searchResults.setResults(responseResult);
			return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
		} catch (SolrServerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	private AjaxResult getSiteMeasurementsBySolr(AssetEventDTO assetEventDTO) {
		try {
			SolrQuery params = new SolrQuery();
			//查询条件
			params.set("q", "eventType:Measurements");

			params = getParams(params, assetEventDTO);

			//yml文件未配置具体的collection，所以此处需要配置
			QueryResponse queryResponse = client.query(core, params);

			SolrDocumentList results = queryResponse.getResults();

			DeviceMeasurementsSearchResults searchResults = new DeviceMeasurementsSearchResults();
			searchResults.setNumResults(results.getNumFound());
			List<DeviceMeasurements> responseResult = new ArrayList<>();
			for (SolrDocument document : results) {
				DeviceMeasurements measurements = new DeviceMeasurements();

				measurements.setId((String) document.get("eventId"));
				measurements.setDeviceAssignmentToken((String) document.get("assignmentToken"));

				String assignmentType = (String) document.get("assignmentType");
				DeviceAssignmentType assignmentTypeEnum = (DeviceAssignmentType) getEnum(assignmentType, DeviceAssignmentType.values());
				measurements.setAssignmentType(assignmentTypeEnum);

				String assetId = (String) document.get("assetId");
				measurements.setAssetId(assetId);
				String siteToken = (String) document.get("siteToken");
				measurements.setSiteToken(siteToken);

				Date eventDate = (Date) document.get("eventDate");
				measurements.setEventDate(eventDate);
				Date receivedDate = (Date) document.get("receivedDate");
				measurements.setReceivedDate(receivedDate);

				Map provider = getmetadata(document, "mx");
				measurements.setMeasurements(provider);

				Map meta = getmetadata(document, "meta");
				measurements.setMetadata(meta);
				responseResult.add(measurements);
			}

			searchResults.setResults(responseResult);
			return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
		} catch (SolrServerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	private AjaxResult getSiteLocationsBySolr(AssetEventDTO assetEventDTO) {
		try {
			SolrQuery params = new SolrQuery();
			//查询条件
			params.set("q", "eventType:Location");

			params = getParams(params, assetEventDTO);

			//yml文件未配置具体的collection，所以此处需要配置
			QueryResponse queryResponse = client.query(core, params);

			SolrDocumentList results = queryResponse.getResults();

			DeviceLocationSearchResults searchResults = new DeviceLocationSearchResults();
			searchResults.setNumResults(results.getNumFound());
			List<DeviceLocation> responseResult = new ArrayList<>();
			for (SolrDocument document : results) {
				DeviceLocation location = new DeviceLocation();

				location.setId((String) document.get("eventId"));
				location.setDeviceAssignmentToken((String) document.get("assignmentToken"));

				String assignmentType = (String) document.get("assignmentType");
				DeviceAssignmentType assignmentTypeEnum = (DeviceAssignmentType) getEnum(assignmentType, DeviceAssignmentType.values());
				location.setAssignmentType(assignmentTypeEnum);

				String assetId = (String) document.get("assetId");
				location.setAssetId(assetId);
				String siteToken = (String) document.get("siteToken");
				location.setSiteToken(siteToken);

				Date eventDate = (Date) document.get("eventDate");
				location.setEventDate(eventDate);
				Date receivedDate = (Date) document.get("receivedDate");
				location.setReceivedDate(receivedDate);

				List ll = (List) document.get("location");
				String latitude_longitude = ll.get(0).toString();
				String[] split = latitude_longitude.split(",");
				Double latitude = Double.parseDouble(split[0]);
				Double longitude = Double.parseDouble(split[1]);
				location.setLatitude(latitude);
				location.setLongitude(longitude);

				Double elevation = (Double) document.get("elevation");
				location.setElevation(elevation);

				Map meta = getmetadata(document, "meta");
				location.setMetadata(meta);
				responseResult.add(location);
			}

			searchResults.setResults(responseResult);
			return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
		} catch (SolrServerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	private Map getmetadata(SolrDocument document, String meta) {
		Map result = new HashMap();
		for (Map.Entry<String, Object> entry : document) {
			if (entry.getKey().contains(meta)) {
				result.put(entry.getKey().replace(meta + ".", ""), entry.getValue());
			}
		}
		return result;
	}

	private Enum getEnum(String level, Enum[] values) {
		for (Enum a : values) {
			if (level.equals(a.toString())) {
				return a;
			}
		}
		return null;
	}

	private SolrQuery getParams(SolrQuery params, AssetEventDTO assetEventDTO) {
		String param_siteToken = "";
		if (StringUtils.isNotBlank(assetEventDTO.getSiteid())) {
			SiteModel siteModel = siteService.selectById(assetEventDTO.getSiteid());
			if (StringUtils.isNotBlank(siteModel.getSitetoken())) {
				param_siteToken = siteModel.getSitetoken();
			}
		}
		if (StringUtils.isNotBlank(param_siteToken)) {
			params.set("fq", "siteToken:" + param_siteToken);
		}
		String param_assetId = assetEventDTO.getAssetid();
		if (StringUtils.isNotBlank(param_assetId)) {
			params.set("fq", "assetId:" + param_assetId);
		}

		String param_assignmentToken = assetEventDTO.getAssignmentToken();
		if (StringUtils.isNotBlank(param_assignmentToken)) {
			params.set("fq", "assignmentToken:" + param_assignmentToken);
		}

		//分页,page=1,pagesize=0的时候查询所有
		if(assetEventDTO.getPage() == 1 && assetEventDTO.getPagesize() == 0){
			params.setStart(assetEventDTO.getPage() - 1);
			params.setRows(Integer.MAX_VALUE);
		}else{
			params.setStart((assetEventDTO.getPage() - 1)*assetEventDTO.getPagesize());
			params.setRows(assetEventDTO.getPagesize());
		}
		return params;
	}

	//以下方法为通过接口查询
	private AjaxResult getSiteAlerts(AssetEventDTO assetEventDTO) {
		DateRangeSearchCriteria criteria = new DateRangeSearchCriteria(assetEventDTO.getPage(), assetEventDTO.getPagesize(), null, null);
		DeviceAlertSearchResults searchResults = null;
		SiteModel siteModel = siteService.selectById(assetEventDTO.getSiteid());
		try {
			//searchResults = client.listDeviceLocationsForSite("bb105f8d-3150-41f5-b9d1-db04965668d3", criteria);
			searchResults = smartThingClient.listDeviceAlertsForSite(siteModel.getSitetoken(), criteria);
		} catch (SmartThingException e) {
			e.printStackTrace();
			return new AjaxResult(ErrorCodeConstants.INTERNAL_ERROR, "系统内部错误", searchResults, "系统内部错误");
		}
		return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
	}

	private AjaxResult getSiteLocations(AssetEventDTO assetEventDTO) {
		DateRangeSearchCriteria criteria = new DateRangeSearchCriteria(assetEventDTO.getPage(), assetEventDTO.getPagesize(), null, null);
		DeviceLocationSearchResults searchResults = null;
		SiteModel siteModel = siteService.selectById(assetEventDTO.getSiteid());
		try {
			//searchResults = client.listDeviceLocationsForSite("bb105f8d-3150-41f5-b9d1-db04965668d3", criteria);
			searchResults = smartThingClient.listDeviceLocationsForSite(siteModel.getSitetoken(), criteria);
		} catch (SmartThingException e) {
			e.printStackTrace();
			return new AjaxResult(ErrorCodeConstants.INTERNAL_ERROR, "系统内部错误", searchResults, "系统内部错误");
		}
		return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
	}

	private AjaxResult getSiteMeasurements(AssetEventDTO assetEventDTO) {
		DateRangeSearchCriteria criteria = new DateRangeSearchCriteria(assetEventDTO.getPage(), assetEventDTO.getPagesize(), null, null);
		DeviceMeasurementsSearchResults searchResults = null;
		SiteModel siteModel = siteService.selectById(assetEventDTO.getSiteid());
		try {
			//searchResults = client.listDeviceMeasurementsForSite("bb105f8d-3150-41f5-b9d1-db04965668d3", criteria);
			searchResults = smartThingClient.listDeviceMeasurementsForSite(siteModel.getSitetoken(), criteria);
		} catch (SmartThingException e) {
			e.printStackTrace();
			return new AjaxResult(ErrorCodeConstants.INTERNAL_ERROR, "系统内部错误", searchResults, "系统内部错误");
		}
		return new AjaxResult(ErrorCodeConstants.SUCCESS, "获取成功", searchResults, "获取成功");
	}

	public static void main(String[] args) throws Exception {
		/*ISmartThingClient client = new SmartThingClient("http://10.12.8.223:26666/smartthing/api/", "admin", "password");
		DateRangeSearchCriteria criteria = new DateRangeSearchCriteria(1, 10, null, null);
		DeviceMeasurementsSearchResults searchResults = client.listDeviceMeasurementsForSite("bb105f8d-3150-41f5-b9d1-db04965668d3", criteria);
		//DeviceLocationSearchResults searchResults = client.listDeviceLocationsForSite("bb105f8d-3150-41f5-b9d1-db04965668d3", criteria);
		System.out.println(searchResults.getResults().size());*/
	}
}
